<?php

namespace app\api\controller;

use app\admin\model\User;
use app\common\controller\Api;
use fast\Http;
use fast\Random;
use think\Cache;
use think\Config;
use think\Exception;

/**
 * 微信认证接口
 */
class Wxauth extends Api
{



    // 无需登录的接口,*表示全部
    protected $noNeedLogin = ['Silentlogin'];
    // 无需鉴权的接口,*表示全部
    protected $noNeedRight = ['*'];
    protected $appid;
    protected $secret;
    protected $loginUrl;

    // 初始化方法
    public function _initialize()
    {

        $this->appid = '*****';
        $this->secret = '*****';
        $this->loginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
        // parent::__construct();
        parent::_initialize();
    }

    /**
     * 微信认证
     *
     */
    public function index()
    {
        $this->success('微信认证请求成功');
    }

    /**
     * 登录第一步，获取openid 跟 session_key
     */
    // public function code()
    // {
    //     $code = $this->request->param('code');
    //     if (!$code) {
    //         $this->error('code不能为空');
    //     }
    //     self::getOpenid($code);
    // }

    // /**
    //  * 用户登录
    //  */
    // public function login()
    // {
    //     $encryptedData = $this->request->post('encryptedData');
    //     $iv = $this->request->post('iv');
    //     $sessionKey = $this->request->post('sessionKey');
    //     $openid = $this->request->post('openid');

    //     if (empty($encryptedData) || empty($iv) || empty($sessionKey) || empty($openid)) {
    //         $this->error('缺少参数');
    //     }
    //     $errCode = self::decryptData($encryptedData, $iv, $data, $sessionKey, $this->appid);
    //     if ($errCode == 0) {
    //         $result = json_decode($data, true);

    //         $userinfo = \app\admin\model\User::where(['openid' => $openid])->find();

    //         if ($userinfo) {
    //             $userinfo->nickname = $result['nickName'];
    //             $userinfo->avatar = $result['avatarUrl'];
    //             $userinfo->gender = $result['gender'];
    //             $userinfo->city = $result['city'];
    //             $userinfo->province = $result['province'];
    //             $userinfo->country = $result['country'];
    //             $userinfo->save();
    //             $this->auth->direct($userinfo['id']);
    //         } else {
    //             $user = new \app\admin\model\User();
    //             $user->data([
    //                 'nickname' => $result['nickName'],
    //                 'avatar' => $result['avatarUrl'],
    //                 'gender' => $result['gender'],
    //                 'city' => $result['city'],
    //                 'province' => $result['province'],
    //                 'country' => $result['country'],
    //                 'status' => 'normal',
    //                 'openid' => $openid
    //             ]);
    //             $user->save();
    //             $this->auth->direct($user->id);
    //         }
    //         $this->success('登录成功', $this->auth->getUserinfo());
    //     } else {
    //         $this->error('登录失败' . $errCode);
    //     }
    // }


    // /**
    //  * @param $code 用来交换获取openid 跟 session_key
    //  */
    // public function getOpenid($code)
    // {
    //     $url = sprintf($this->loginUrl, $this->appid, $this->secret, $code);
    //     $result = Http::get($url);
    //     $wxResult = json_decode($result, true);
    //     if (empty($wxResult)) {
    //         $this->error('获取sessin_key及openID时异常');
    //     }
    //     if (isset($wxResult['errcode']) && $wxResult['errcode'] != 0) {
    //         $this->error($wxResult['errmsg']);
    //     }
    //     $item = [
    //         'openid' => $wxResult['openid'],
    //         'session_key' => $wxResult['session_key']
    //     ];
    //     $this->success('成功', $item);
    // }



    // 抄黄山学院的接口文档接口可以了
    // 检测是否有账号
    public function Silentlogin()
    {
        // 0b3HYj100pefsT1DyF100xuUbv1HYj1t
        $code = $this->request->param('code', '');
        if (!$code) {
            $this->error('参数错误');
        }
        $url = sprintf('https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code', $this->appid, $this->secret, $code);
        $result = Http::get($url);
        $wxResult = json_decode($result, true);
        if (empty($wxResult)) {
            $this->error('获取sessin_key及openID时异常');
        }
        if (isset($wxResult['errcode']) && $wxResult['errcode'] != 0) {
            $this->error($wxResult['errmsg']);
        }

        $ret = User::where('openid', $wxResult['openid'])->find();
        if ($ret) {
            // 直接登录成功
            $ret = $this->auth->direct($ret['id']);
            if ($ret) {
                $retdata = $this->auth->getUserinfo();
                $this->success('已有账号', $retdata);
            } else {
                $this->error('登录失败请重试');
            }
        } else {
            // 注册账号登录成功
            $time = time();
            $data = [
                'username' => Random::alnum(6),
                'password' => Random::alnum(6),
                'nickname'  => Random::alnum(6),
                'jointime'  => $time,
                'logintime' => $time,
                'prevtime'  => $time,
                'openid'  => $wxResult['openid'],
                'status'    => 'normal'
            ];

            $user = new User;
            $user->data($data);
            $ret = $user->save();
            if ($ret) {
                $ret = $this->auth->direct($user->id);
                if ($ret) {
                    $retdata = $this->auth->getUserinfo();
                    $this->success('注册成功', $retdata);
                } else {
                    $this->error('登录失败请重试');
                }
            } else {
                $this->error('注册失败请重试');
            }
        }
    }

    // 获取用户信息
    public function userinfo()
    {
        $userinfo = User::where('id', $this->auth->id)->field('id,uid,avatar,nickname,username,gender,birthday,address,mobile,province,city,area,province_name,city_name,area_name')->find();
        $this->success('请求成功', $userinfo);
    }


    // 获取手机号
    public function getMobile()
    {
        $code = $this->request->param('code', '');
        if (!$code) {
            $this->error('参数错误');
        }
        $phoneInfo = $this->getWechatMobile($code);
        if (!empty($phoneInfo) && isset($phoneInfo['phoneNumber'])) {
            $user = User::where('id', $this->auth->id)->find();
            if ($user) {
                $user->mobile = $phoneInfo['phoneNumber'];
                $user->save();
                $this->success('手机号更新成功', $phoneInfo);
                // if ($user->save()) {
                //     $this->success('手机号更新成功', $phoneInfo);
                // } else {
                //     $this->error('手机号更新失败');
                // }
            } else {
                $this->error('用户不存在');
            }
        } else {
            $this->error('获取手机号失败');
        }
    }
    //获取手机号
    public function getWechatMobile($code)
    {
        // 最多重试2次
        $maxRetry = 2;
        $retry = 0;

        while ($retry < $maxRetry) {
            $access_token = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={$access_token}";
            $res = Http::post($url, json_encode(['code' => $code]));
            $res = (array)json_decode($res, true);

            // 如果返回40001错误码（access_token失效），清除缓存并重试
            if (isset($res['errcode']) && $res['errcode'] == 40001) {
                Cache::rm('access_token' . $this->appid);
                if (Config::get('app_debug')) {
                    \think\Log::write('access_token失效，尝试重新获取，重试次数: ' . ($retry + 1), 'info');
                }
                $retry++;
                continue;
            }

            // 成功获取手机号
            if (isset($res['phone_info'])) {
                return $res['phone_info'];
            }

            // 其他错误
            if (Config::get('app_debug')) {
                \think\Log::write('获取手机号失败: ' . json_encode($res), 'error');
            }
            break;
        }

        return [];
    }

    //获取access_token
    public function setAccessToken()
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appid . '&secret=' . $this->secret;

        $res = Http::get($url);
        $res = (array)json_decode($res, true);

        if (isset($res['access_token'])) {
            $access_token = $res['access_token'];
            // 微信access_token有效期7200秒，提前200秒过期，避免临界点问题
            Cache::set('access_token' . $this->appid, $access_token, 7000);
            return $access_token;
        } else {
            // 记录错误日志
            if (Config::get('app_debug')) {
                \think\Log::write('获取access_token失败: ' . json_encode($res), 'error');
            }
            // 如果获取失败，抛出异常
            throw new Exception('获取access_token失败: ' . ($res['errmsg'] ?? '未知错误'));
        }
    }

    public function getUserInfo()
    {
        $user = $this->auth->getUserinfo();
        $this->success('请求成功', $user);
    }

    /**
     * Notes: 获取accessToken
     * Author: L,Z
     * Date: 2024/4/29 15:18
     */
    public function getAccessToken()
    {
        $cacheKey = 'access_token' . $this->appid;
        $accessToken = Cache::get($cacheKey);

        if (!$accessToken) {
            // 使用锁机制，防止并发请求同时刷新token
            $lockKey = 'lock_' . $cacheKey;
            $lock = Cache::get($lockKey);

            if (!$lock) {
                // 设置锁，5秒过期
                Cache::set($lockKey, 1, 5);
                try {
                    $accessToken = $this->setAccessToken();
                } catch (Exception $e) {
                    // 释放锁
                    Cache::rm($lockKey);
                    throw $e;
                }
                // 释放锁
                Cache::rm($lockKey);
            } else {
                // 等待其他进程获取token
                sleep(1);
                $accessToken = Cache::get($cacheKey);
                if (!$accessToken) {
                    // 如果还是没有，自己尝试获取
                    $accessToken = $this->setAccessToken();
                }
            }
        }

        return $accessToken;
    }

    // 再加一个更新头像昵称的接口 nickname avatar
    public function updateUserInfo()
    {
        $nickname = $this->request->param('nickname', '');
        $avatar = $this->request->param('avatar', '');
        $mobile = $this->request->param('mobile', '');
        $student_number = $this->request->param('student_number', '');

        if (empty($nickname) && empty($avatar) && !$this->request->file('file')) {
            $this->error('参数错误');
        }



        $user = \app\admin\model\User::where('id', $this->auth->id)->find();
        if ($user) {
            if (!empty($nickname)) {
                $user->nickname = $nickname;
            }
            if (!empty($avatar)) {
                $user->avatar = $avatar;
            }
            if (!empty($mobile)) {
                $user->mobile = $mobile;
            }
            if (!empty($student_number)) {
                $user->student_number = $student_number;
            }
            // 更新时间
            $user->updatetime = time();
            $user->save();
            $this->success('更新成功');
        } else {
            $this->error('用户不存在');
        }
    }
}
